package com.example.javabasic.thread.classone.threadpool;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * 自定义线程池
 * 视频资料 : https://www.bilibili.com/video/BV1L4411i7eW?p=37
 */
public class CustomThreadPool {

    /**
     * 1. 创建线程池, 然后根据size 创建size个数的 重写Thread 类实例 ,放入 Thread类实例队列中
     * 2. 将所有Runnable 任务放入Runnable队列中   并且每次放入的时候都唤醒一次
     * 3.
     */

    //线程池大小
    private final int size;
    //默认线程池大小(不手动设置时给的默认值)
    private final static int DEFAULT_SIZE = 10;
    //自增id
    private static volatile int seq = 0;
    //线程名字前缀
    private static String perfix = "CustomPool-";
    //创建一个线程组  用来初始化线程的时候使用
    private static final ThreadGroup group = new ThreadGroup("CustomPoolGroup");
    //任务队列  先进先出
    private final static Queue<Runnable> RUNNABLE_QUEUE = new ArrayDeque<>();
    //定义线程队列  ,用其中的线程去跑 任务队列中的任务
    private static final Queue<WorkTask>  THREAD_QUEUE = new ArrayDeque<>();


    //提供外部提交任务接口
    public void submit(Runnable runnable){
        synchronized (RUNNABLE_QUEUE){
            //提交任务
            RUNNABLE_QUEUE.offer(runnable);
            //唤醒队列线程
            RUNNABLE_QUEUE.notifyAll();
        }
    }

    //构造器
    public CustomThreadPool() {
        this(DEFAULT_SIZE);
        init();
    }
    //定长构造器
    public CustomThreadPool(int size) {
        this.size = size;
        init();
    }

    //初始化器
    public void init() {
        //根据给的初始长度 ,创建任务  ,放入工作队列
        for (int i = 0; i < size; i++) {
            createWorkTask();
        }
    }

    private void createWorkTask(){
        createWorkTask("");
    }

    private void createWorkTask(String name) {
        WorkTask task = new WorkTask(group, perfix + name + (seq++));
        THREAD_QUEUE.offer(task);
        task.start();
    }

    //枚举  FREE:完成, RUNNING:运行中   BLOCKED:阻塞中  DEAD  死亡
    private enum TaskState {
        FREE, RUNNING, BLOCKED, DEAD;
    }

    public void close(){
        THREAD_QUEUE.forEach(n->n.close());
    }

    private static class WorkTask extends Thread {
        private volatile TaskState taskState = TaskState.FREE;

        public TaskState getTaskState() {
            return this.taskState;
        }


        /**
         * 重写父类(Thread) 的构造器
         */
        public WorkTask(ThreadGroup threadGroup, String name) {
            super(threadGroup, name);
            //关闭线程池时强制关闭线程
//            super.setDaemon(true);
        }


        //重写Thread 类的 run方法
        @Override
        public void run() {
            OUT:
            while (this.taskState != TaskState.DEAD) {
                //当不是死亡状态的时候  进入这里
                Runnable runnable = null;
                synchronized (RUNNABLE_QUEUE) {
                    //当任务队列位空的时候 队列等待
                    while (RUNNABLE_QUEUE.isEmpty()) {
                        try {
                            //进入阻塞状态
                            this.taskState = TaskState.BLOCKED;
                            RUNNABLE_QUEUE.wait();
                        } catch (InterruptedException e) {
                            //当阻塞被打断的时候,  跳出while循环, 到OUT位置 往下执行
                            break OUT;
                        }
                    }
                    //获取队列中最先进入的任务
                    runnable = RUNNABLE_QUEUE.poll();
                }
                if (runnable != null) {
                    //更改状态位运行中
                    this.taskState = TaskState.RUNNING;
                    runnable.run();
                    //运行完成
                    this.taskState = TaskState.FREE;
                }
            }
        }


        public void close() {
            this.taskState = TaskState.DEAD;
        }
    }







    public static void main(String[] args) {
        CustomThreadPool pool = new CustomThreadPool(4);
        for (int i = 0; i < 40; i++) {
            int n = i;
            pool.submit(()->{
                System.out.println("当前线程:"+Thread.currentThread().getName()+"   ->"+n);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        Thread thread = new Thread();

        System.out.println("40个任务已经放入 RUNNABLE_QUEUE中");

    }
}
